package com.zcxk.web;

import com.zcxk.constant.Constants;
import com.zcxk.dao.JdbcPool;
import com.zcxk.web.handler.*;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Promise;
import io.vertx.core.Vertx;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.client.WebClient;
import io.vertx.ext.web.client.WebClientOptions;
import io.vertx.ext.web.handler.BodyHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class WebAPP extends AbstractVerticle {

  private static final Logger logger = LoggerFactory.getLogger(WebAPP.class);
  private static final int MAX_RETRY_ATTEMPTS = 5;

  public static void main(String[] args) {
    System.setProperty("vertx.logger-delegate-factory-class-name", "io.vertx.core.logging.Log4j2LogDelegateFactory");

    WebAPP verticle = new WebAPP();
    Vertx vertx = Vertx.vertx();

    // 部署verticle，这里会调用start方法
    vertx.deployVerticle(verticle);
  }

  @Override
  public void start(Promise<Void> startPromise) throws Exception {
    attemptServerStart(0, startPromise);
  }

  private void attemptServerStart(int retry, Promise<Void> startPromise) {
    // 创建路由对象
    Router mainRouter = Router.router(vertx);

    WebClientOptions options = new WebClientOptions();
    options.setMaxPoolSize(Constants.getMaxHTTPPoolSize());
    options.setDefaultHost(Constants.getServerHost());
    options.setDefaultPort(Constants.getDcpApiServerPort());
    WebClient client = WebClient.create(vertx, options);

    try {
      boolean initJdbcSuccess = JdbcPool.init(vertx);
      if (initJdbcSuccess) {
        System.out.println("init mysql success");
      } else {
        throw new Exception("Failed to initialize JDBC pool");
      }

      // 允许解析requestBody以及文件上传
      mainRouter.route().handler(BodyHandler.create());
      mainRouter.post("/user/login").handler(new LoginHandler());
      mainRouter.get("/api/*").handler(new CheckTokenHandler());
      mainRouter.get("/api/activeDevices").handler(new GetActiveDevicesHandler(client));
      mainRouter.get("/api/history/hr").handler(new HistoryHrHandler(client));
      mainRouter.get("/api/history/spo2").handler(new HistorySpo2Handler(client));
      mainRouter.get("/api/history/resp").handler(new HistoryRespHandler(client));
      mainRouter.get("/api/history/nibp").handler(new HistoryNibpHandler(client));
      mainRouter.get("/api/history/temp").handler(new HistoryTempHandler(client));

      vertx.createHttpServer()
        .requestHandler(mainRouter)
        .listen(Constants.getWebServerPort(), http -> {
          if (http.succeeded()) {
            startPromise.complete();
            logger.info("Web server started on port {}", Constants.getWebServerPort());
          } else {
            handleStartupFailure(retry, startPromise, http.cause());
          }
        });
    } catch (Exception e) {
      handleStartupFailure(retry, startPromise, e);
    }
  }

  private void handleStartupFailure(int retry, Promise<Void> startPromise, Throwable cause) {
    if (retry >= MAX_RETRY_ATTEMPTS) {
      logger.error("Server startup failed after {} attempts. Last error: {}",
        MAX_RETRY_ATTEMPTS, cause.getMessage());
      startPromise.fail(cause);
    } else {
      long backoff = (long) (Math.pow(2, retry) * 1000); // 指数退避，单位为毫秒
      logger.warn("Server startup attempt {} failed. Retrying in {} ms. Error: {}",
        retry + 1, backoff, cause.getMessage());

      vertx.setTimer(backoff, timer -> {
        attemptServerStart(retry + 1, startPromise);
      });
    }
  }
}
